#include "NeoBiCalibroPrivate.h"
#include <QPainterPath>
#include <qmath.h>

NeoBiCalibroPrivate::NeoBiCalibroPrivate(QObject *parent)
    : QObject(parent),
      pValue(0),
      pTickInterval(5),
      pMajorTickInterval(0),
      pTextTickInterval(0),
      pMinAngle(0),
      pMaxAngle(180),
      pShowNotches(true),
      pShowMarkers(true),
      pPointerColor(Qt::green),
      pBackgroundColor(Qt::gray),
      pNotchColor(Qt::gray),
      pMarkerColor(Qt::gray),
      pIndicatorRadius(100),
      pCircleCenter(0, 0),
      pCurrentSpinAngle(180)
{
}

NeoBiCalibroPrivate::~NeoBiCalibroPrivate() = default;

int NeoBiCalibroPrivate::realAngleToVirtualAngle(int angle)
{
    return (angle - (pMinAngle + pCurrentSpinAngle / 2) + 360) % 360;
}

int NeoBiCalibroPrivate::virtualAngleToRealAngle(int angle)
{
    angle = angle > 180 ? angle - 360 : angle;
    int result = angle + pMinAngle + pCurrentSpinAngle / 2;
    if (result < pMinAngle)
    {
        result = pMinAngle;
    }
    else if (result > pMaxAngle)
    {
        result = pMaxAngle;
    }
    return result;
}

int NeoBiCalibroPrivate::mousePositionForAngle(QPointF pos)
{
    qreal dx = pos.x() - pCircleCenter.x();
    qreal dy = pos.y() - pCircleCenter.y();
    int angle = qAtan2(-dy, dx) * 180 / M_PI;
    angle = 360 - (angle + 360 + 270) % 360;
    return virtualAngleToRealAngle(angle);
}

void NeoBiCalibroPrivate::updateWidgetGeometry(QSize size)
{
    if (pCurrentSpinAngle <= 90)
    {
        pIndicatorRadius = size.height() / 2;
    }
    else
    {
        pIndicatorRadius = size.height() / (1 + qCos(qDegreesToRadians(180.0 - pCurrentSpinAngle)));
    }
    pCircleCenter = QPointF(size.width() / 2.0, pIndicatorRadius + pSpace);
}

void NeoBiCalibroPrivate::drawBackground(QPainter *painter)
{
    painter->save();
    painter->setPen(QPen(Qt::gray, 2));
    painter->drawArc(pCircleCenter.x() - pIndicatorRadius, pCircleCenter.y() - pIndicatorRadius, 2 * pIndicatorRadius, 2 * pIndicatorRadius, (90 + pCurrentSpinAngle / 2) * 16, -pCurrentSpinAngle * 16);
    painter->restore();
}

void NeoBiCalibroPrivate::drawNotches(QPainter *painter)
{
    if (pShowNotches)
    {

        painter->save();
        painter->setPen(QPen(pPointerColor, 2));
        painter->setFont(QFont("Arial", 10));
        painter->translate(pCircleCenter);
        painter->rotate(-pCurrentSpinAngle / 2);
        for (int i = pMinAngle; i <= pMaxAngle; i += pTickInterval)
        {
            QLineF line(0, -pIndicatorRadius, 0, -pIndicatorRadius + (pTextTickInterval != 0 && i % pTextTickInterval == 0 ? 15 : (pMajorTickInterval != 0 && i % pMajorTickInterval == 0 ? 10 : 5)));
            painter->drawLine(line);
            if (pTextTickInterval != 0 && i % pTextTickInterval == 0)
            {
                if (i != pMinAngle || pCurrentSpinAngle != 360 ||
                    pMinAngle % pTextTickInterval != 0 || pMaxAngle % pTextTickInterval != 0)
                {
                    QRect textRect(-25, -pIndicatorRadius + 20, 50, 20);
                    painter->drawText(textRect, Qt::AlignCenter, QString::number(i));
                }
            }
            painter->rotate(pTickInterval);
        }
        painter->restore();
    }
}

void NeoBiCalibroPrivate::drawPointer(QPainter *painter)
{
    painter->save();
    QPainterPath path;
    path.moveTo(0, -pIndicatorRadius);
    path.lineTo(-5, 5);
    path.arcTo(-5, 0, 10, 10, 180, 180);
    path.lineTo(0, -pIndicatorRadius);
    path.closeSubpath();
    painter->translate(pCircleCenter);
    painter->rotate(realAngleToVirtualAngle(pValue));
    painter->fillPath(path, pPointerColor);
    painter->restore();
}

void NeoBiCalibroPrivate::drawMarks(QPainter *painter)
{
    if (pShowMarkers)
    {
        painter->save();
        painter->setPen(pMarkerColor);
        QRect markRect(pCircleCenter.x() - 25, pCircleCenter.y() + 20, 50, 20);
        painter->drawText(markRect, Qt::AlignCenter, QString::number(pValue));
        painter->restore();
    }
}